home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Berkeley DB 1.8.5a / recno / rec_open.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-15  |  6.7 KB  |  248 lines  |  [TEXT/CWIE]

  1. /*-
  2.  * Copyright (c) 1990, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Mike Olson.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. static char sccsid[] = "@(#)rec_open.c    8.10 (Berkeley) 9/1/94";
  39. #endif /* LIBC_SCCS and not lint */
  40.  
  41. #include <sys/types.h>
  42. #ifndef macintosh
  43. #include <sys/mman.h>
  44. #endif
  45. #include <sys/stat.h>
  46.  
  47. #include <errno.h>
  48. #include <fcntl.h>
  49. #include <limits.h>
  50. #include <stddef.h>
  51. #include <stdio.h>
  52. #include <unistd.h>
  53.  
  54. #include <db.h>
  55. #include "recno.h"
  56.  
  57. #ifdef macintosh
  58. FILE * fdopen(int, const char *);
  59. #endif
  60.  
  61. DB *
  62. __rec_open(fname, flags, mode, openinfo, dflags)
  63.     const char *fname;
  64.     int flags, mode, dflags;
  65.     const RECNOINFO *openinfo;
  66. {
  67.     BTREE *t;
  68.     BTREEINFO btopeninfo;
  69.     DB *dbp;
  70.     PAGE *h;
  71.     struct stat sb;
  72.     int rfd, sverrno;
  73.  
  74.     /* Open the user's file -- if this fails, we're done. */
  75.     if (fname != NULL && (rfd = DB_open(fname, flags, mode)) < 0)
  76.         return (NULL);
  77.  
  78.     /* Create a btree in memory (backed by disk). */
  79.     dbp = NULL;
  80.     if (openinfo) {
  81.         if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
  82.             goto einval;
  83.         btopeninfo.flags = 0;
  84.         btopeninfo.cachesize = openinfo->cachesize;
  85.         btopeninfo.maxkeypage = 0;
  86.         btopeninfo.minkeypage = 0;
  87.         btopeninfo.psize = openinfo->psize;
  88.         btopeninfo.compare = NULL;
  89.         btopeninfo.prefix = NULL;
  90.         btopeninfo.lorder = openinfo->lorder;
  91.         dbp = __bt_open(openinfo->bfname,
  92.             O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
  93.     } else
  94.         dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
  95.     if (dbp == NULL)
  96.         goto err;
  97.  
  98.     /*
  99.      * Some fields in the tree structure are recno specific.  Fill them
  100.      * in and make the btree structure look like a recno structure.  We
  101.      * don't change the bt_ovflsize value, it's close enough and slightly
  102.      * bigger.
  103.      */
  104.     t = dbp->internal;
  105.     if (openinfo) {
  106.         if (openinfo->flags & R_FIXEDLEN) {
  107.             F_SET(t, R_FIXLEN);
  108.             t->bt_reclen = openinfo->reclen;
  109.             if (t->bt_reclen == 0)
  110.                 goto einval;
  111.         }
  112.         t->bt_bval = openinfo->bval;
  113.     } else
  114.         t->bt_bval = '\n';
  115.  
  116.     F_SET(t, R_RECNO);
  117.     if (fname == NULL)
  118.         F_SET(t, R_EOF | R_INMEM);
  119.     else
  120.         t->bt_rfd = rfd;
  121.  
  122.     if (fname != NULL) {
  123.         /*
  124.          * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
  125.          * Unfortunately, that's not portable, so we use lseek
  126.          * and check the errno values.
  127.          */
  128.         errno = 0;
  129.         if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
  130.             switch (flags & O_ACCMODE) {
  131.             case O_RDONLY:
  132.                 F_SET(t, R_RDONLY);
  133.                 break;
  134.             default:
  135.                 goto einval;
  136.             }
  137. slow:            if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
  138.                 goto err;
  139.             F_SET(t, R_CLOSEFP);
  140.             t->bt_irec =
  141.                 F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
  142.         } else {
  143.             switch (flags & O_ACCMODE) {
  144.             case O_RDONLY:
  145.                 F_SET(t, R_RDONLY);
  146.                 break;
  147.             case O_RDWR:
  148.                 break;
  149.             default:
  150.                 goto einval;
  151.             }
  152.  
  153.             if (fstat(rfd, &sb))
  154.                 goto err;
  155.             /*
  156.              * Kluge -- we'd like to test to see if the file is too
  157.              * big to mmap.  Since, we don't know what size or type
  158.              * off_t's or size_t's are, what the largest unsigned
  159.              * integral type is, or what random insanity the local
  160.              * C compiler will perpetrate, doing the comparison in
  161.              * a portable way is flatly impossible.  Hope that mmap
  162.              * fails if the file is too large.
  163.              */
  164.             if (sb.st_size == 0)
  165.                 F_SET(t, R_EOF);
  166.             else {
  167. #ifdef MMAP_NOT_AVAILABLE
  168.                 /*
  169.                  * XXX
  170.                  * Mmap doesn't work correctly on many current
  171.                  * systems.  In particular, it can fail subtly,
  172.                  * with cache coherency problems.  Don't use it
  173.                  * for now.
  174.                  */
  175.                 t->bt_msize = sb.st_size;
  176.                 if ((t->bt_smap = mmap(NULL, t->bt_msize,
  177.                     PROT_READ, MAP_PRIVATE, rfd,
  178.                     (off_t)0)) == (caddr_t)-1)
  179.                     goto slow;
  180.                 t->bt_cmap = t->bt_smap;
  181.                 t->bt_emap = t->bt_smap + sb.st_size;
  182.                 t->bt_irec = F_ISSET(t, R_FIXLEN) ?
  183.                     __rec_fmap : __rec_vmap;
  184.                 F_SET(t, R_MEMMAPPED);
  185. #else
  186.                 goto slow;
  187. #endif
  188.             }
  189.         }
  190.     }
  191.  
  192.     /* Use the recno routines. */
  193.     dbp->close = __rec_close;
  194.     dbp->del = __rec_delete;
  195.     dbp->fd = __rec_fd;
  196.     dbp->get = __rec_get;
  197.     dbp->put = __rec_put;
  198.     dbp->seq = __rec_seq;
  199.     dbp->sync = __rec_sync;
  200.  
  201.     /* If the root page was created, reset the flags. */
  202.     if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
  203.         goto err;
  204.     if ((h->flags & P_TYPE) == P_BLEAF) {
  205.         F_CLR(h, P_TYPE);
  206.         F_SET(h, P_RLEAF);
  207.         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  208.     } else
  209.         mpool_put(t->bt_mp, h, 0);
  210.  
  211.     if (openinfo && openinfo->flags & R_SNAPSHOT &&
  212.         !F_ISSET(t, R_EOF | R_INMEM) &&
  213.         t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
  214.                 goto err;
  215.     return (dbp);
  216.  
  217. einval:    errno = EINVAL;
  218. err:    sverrno = errno;
  219.     if (dbp != NULL)
  220.         (void)__bt_close(dbp);
  221.     if (fname != NULL)
  222.         (void)close(rfd);
  223.     errno = sverrno;
  224.     return (NULL);
  225. }
  226.  
  227. int
  228. __rec_fd(dbp)
  229.     const DB *dbp;
  230. {
  231.     BTREE *t;
  232.  
  233.     t = dbp->internal;
  234.  
  235.     /* Toss any page pinned across calls. */
  236.     if (t->bt_pinned != NULL) {
  237.         mpool_put(t->bt_mp, t->bt_pinned, 0);
  238.         t->bt_pinned = NULL;
  239.     }
  240.  
  241.     /* In-memory database can't have a file descriptor. */
  242.     if (F_ISSET(t, R_INMEM)) {
  243.         errno = ENOENT;
  244.         return (-1);
  245.     }
  246.     return (t->bt_rfd);
  247. }
  248.